package imlayer

import (
    "time"
	"strconv"
	"wxsdk/oauth"
	"encoding/json"
	"dhfshop/domain/pay"
	"dhfshop/models/im"
	"dhfshop/models/isv"
	"dhfshop/models/org"
	"dhfshop/models/member"
	"dhfshop/models/consts"
	"github.com/astaxie/beego/orm"
	"github.com/astaxie/beego"
	"dhfshop/service/nsqcli"
)

type PushMsgSvr struct {
	PushDao chan *map[string]string
}

var PushMsgSvrIns *PushMsgSvr

func NewPushMsgSvr() *PushMsgSvr {
	return &PushMsgSvr{
		PushDao: make(chan *map[string]string, 1000), //消息中间件中最多1000条数据同时处理
	}
}

func (r *PushMsgSvr) Run() {
	for {
		select {
		case req := <-r.PushDao:
			localKind := (*req)["LocalKind"]
			switch localKind {
				case "COMMON_MESSAGE":
					r.msgComHandle(*req)
				case "AUTHORIZE_EVENT":
				    r.msgAuthHandle(*req)
                case "PAY_NOTIFY":
				    paylayer.MsgPayHandle(*req)
				case "BALANCE_PAY":
				    paylayer.BalancePayHandle(*req)
				case "ROYAL_PAY_NOTIFY":
				    paylayer.MsgRoyPayHandle(*req)
				case "YABAND_PAY_NOTIFY":
				    paylayer.MsgYabandPayHandle(*req)
				case "SUPER_PAY_NOTIFY":
				    paylayer.MsgSuperPayHandle(*req)
				case "USAGMS_PAY_NOTIFY":
				    paylayer.MsgUsagmsHandle(*req)
				case "DAHL_PAY_NOTIFY":
				    paylayer.MsgDahlPayHandle(*req)
				case "WISE_PAY_NOTIFY":
				    paylayer.MsgWiseCashierHandle(*req)
				case "MEGAEZGO_NOTIFY":
				    paylayer.MsgMegaezgoHandle(*req)
				case "CHINAUMS_NOTIFY":
				    paylayer.MsgChinaUmsHandle(*req)
				case "OCEANPAY_NOTIFY":
				    paylayer.MsgOceanPayHandle(*req)
				case "QCUREPAY_NOTIFY":
				    paylayer.MsgQcurePayHandle(*req)
				case "HNAPAY_NOTIFY":
				    paylayer.HnaPayHandle(*req)
				case "ALLINPAY_NOTIFY":
				    paylayer.AllInPayHandle(*req)	
				case "GPSL_PAY_NOTIFY":
				    paylayer.GpslPayHandle(*req)
				default:	
			}
		}
	}
}

func (r *PushMsgSvr) msgComHandle(reqMap map[string]string) (err error) {
	msgReceiptRecord, _:= saveRawMessage(reqMap)
	//查询组织信息进行缓存
	msgUser, err := org.GetCacheServiceUser(msgReceiptRecord.AppId)
	if err != nil {
		beego.Emergency("GetCacheServiceUser appId:", msgReceiptRecord.AppId, err.Error())
		return err
	}
	if msgUser.ServiceTypeId == 1 {  //公众号
	    if _, err := member.GetMemberByOpenId(msgReceiptRecord.FromUserName); err == orm.ErrNoRows {
			if custAccount, err := isv.GetCustAccountByAppId(msgReceiptRecord.AppId); err == nil {
				//beego.Debug("msgType:", msgReceiptRecord.MsgType,"event:", msgReceiptRecord.Event)
				if rslt, err := oauth.GetUserInfo2(custAccount.AccessToken, msgReceiptRecord.FromUserName); err == nil {
					if _, err = member.CreateWeChatMember(msgReceiptRecord.AppId, rslt.OpenID, rslt, 0); err != nil {
					   beego.Debug(err.Error())
					}
				}	
            }
		}
	}
	if msgReceiptRecord.MsgType == "event" {   //事件消息转发
		switch msgReceiptRecord.Event {
			case "user_enter_tempsession":
				//ForwardEnterSessionEvent(msgReceiptRecord)
			case "weapp_audit_success":
			    ForwardAuditSuccessEvent(msgReceiptRecord.AppId, reqMap)
			case "weapp_audit_fail":
			    ForwardAuditFailEvent(msgReceiptRecord.AppId, reqMap)
			case "subscribe":
			    ForwardSubscribeEvent(msgReceiptRecord, reqMap["EventKey"])
			case "unsubscribe":
			    ForwardUnSubscribeEvent(msgReceiptRecord)
			case "SCAN":
			    ForwardScanEvent(msgReceiptRecord, reqMap["EventKey"])
			default:	
		}
	}else{
		ForwardAgentMsg(msgReceiptRecord, msgUser)   // 普通消息转发
	}
    if notifyJson, err := json.Marshal(&reqMap); err == nil {
		address := beego.AppConfig.String("NsqUrl")
		topic := "WxApiMsg"
		if err = nsqcli.StartProducer(address, topic, notifyJson); err != nil {
			beego.Debug("StartProducer err:", err.Error())
		}
	}	
	return nil
}

func (r *PushMsgSvr) msgAuthHandle(reqMap map[string]string) (err error) {
	err = isv.SaveTicketByAppId(reqMap["AppId"],reqMap["ComponentVerifyTicket"],reqMap["CreateTime"])
	if err != nil {
		beego.Debug("SaveTicketByAppId err:", err.Error())
	}
	return nil
}

func saveRawMessage(reqMap map[string]string) (*im.WxMsgReceiptRecords, error) {
	appId := reqMap["AppId"]
	wxCreateTime, _:= strconv.ParseInt(reqMap["CreateTime"], 10, 64)
	msgReceiptRecord := &im.WxMsgReceiptRecords{
		AppId:        appId,
		ToUserName:   reqMap["ToUserName"],
		FromUserName: reqMap["FromUserName"],
		CreateTime:   time.Unix(wxCreateTime, 0),
		MsgId:        reqMap["MsgID"],
		MsgType:      reqMap["MsgType"],
		Status:       consts.STATUS_VALID,
		CreatedAt:    time.Now().UTC(),
	}
	switch reqMap["MsgType"] {
		case "text":
			body := struct {
				Content string `json:"content"` 
			}{}
			if len(reqMap["Content"]) > 0 {
			   body.Content = reqMap["Content"]
			} else {
			   body.Content = ""
			}
			if tmpJson, err := json.Marshal(&body); err == nil {
				msgReceiptRecord.MsgBody = string(tmpJson)
			}
		case "image":
			body := struct {
				MediaId string `json:"media_id"`
				PicURL  string `json:"pic_url"`
			}{MediaId:reqMap["MediaId"], PicURL:reqMap["PicUrl"]}
			if tmpJson, err := json.Marshal(&body); err == nil {
				msgReceiptRecord.MsgBody = string(tmpJson)
			}
		case "miniprogrampage":	
			body := struct {
				Title        string `json:"title"`
				PagePath     string `json:"page_path"`
				ThumbUrl     string `json:"thumb_url"`
				ThumbMediaId string `json:"thumb_media_id"`
			}{Title:reqMap["Title"],PagePath:reqMap["PagePath"],ThumbUrl:reqMap["ThumbUrl"],ThumbMediaId:reqMap["ThumbMediaId"]}
			if tmpJson, err := json.Marshal(&body); err == nil {
				msgReceiptRecord.MsgBody = string(tmpJson)
			}
		case "event":	
			msgReceiptRecord.Event = reqMap["Event"]
			switch reqMap["Event"] {
				case "weapp_audit_fail":
					body := struct {
						Reason string `json:"reason"` 
					}{Reason:reqMap["Reason"]}
					if tmpJson, err := json.Marshal(&body); err == nil {
						msgReceiptRecord.MsgBody = string(tmpJson)
					}
				case "user_enter_tempsession":
					body := struct {
						SessionFrom string `json:"session_from"` 
					}{SessionFrom:reqMap["SessionFrom"]}
					if tmpJson, err := json.Marshal(&body); err == nil {
						msgReceiptRecord.MsgBody = string(tmpJson)
					}
				default:
				    
			}
		default:
		
	}
	if _, err := im.AddWxRecordMessage(msgReceiptRecord); err != nil {
		beego.Emergency(err.Error())
	}
	return msgReceiptRecord, nil
}
